package org.wiztools.oembed;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.logging.Logger;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;

/**
 * Implementation to parse oEmbed XML content.
 * @author subhash
 */
public class OEmbedXmlParser implements OEmbedParser {
    
    private static final Logger LOG = Logger.getLogger(OEmbedXmlParser.class.getName());
    
    /**
     * 
     * @param is The input stream to read XML content from.
     * @param charset The charset to be used for parsing XML content.
     * @return The response.
     * @throws IOException When there are IO issues reading from the stream.
     * @throws OEmbedException Any other reason like when parse-error of XML.
     */
    public OEmbedResponse getResponse(InputStream is, Charset charset) throws IOException,
            OEmbedException {
        try{
            XMLInputFactory f = XMLInputFactory.newInstance();
            f.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false);
            XMLEventReader r = f.createXMLEventReader(is);
            
            OEmbedResponseBuilder builder = new OEmbedResponseBuilder();
            // last element name:
            String eName = null;
            StringBuilder sb = new StringBuilder();
            while(r.hasNext()) {
                XMLEvent event = r.nextEvent();

                if(event.isStartElement()) {
                    StartElement e = (StartElement) event;
                    eName = e.getName().getLocalPart();
                    // Root element should not be processed:
                    if("oembed".equals(eName)) {
                        eName = null;
                    }
                }
                else if(event.isEndElement()) {
                    EndElement e = (EndElement) event;

                    if(eName != null) {
                        builder.addElement(eName, sb.toString());
                    }
                    
                    // Empty:
                    sb.delete(0, sb.length());
                    eName = null;
                }
                else if(event.isCharacters() && eName != null) {
                    final String eValue = event.asCharacters().getData();
                    sb.append(eValue);
                }
            }
            return builder.getResponse();
        }
        catch(XMLStreamException ex) {
            throw new OEmbedException(ex);
        }
    }
}
